package com.yf.mediaserver.gb.sip.processors;

import com.yf.mediaserver.gb.sip.processors.req.ISIPRequestProcessor;
import com.yf.mediaserver.gb.sip.processors.resp.ISIPResponseProcessor;
import com.yf.mediaserver.gb.sip.processors.timeout.ITimeoutProcessor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.sip.*;
import javax.sip.header.CSeqHeader;
import javax.sip.header.CallIdHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 监听SIP协议消息 具体实现
 */
@Slf4j
@Component
public class SIPProcessorObserver implements SipListener {


    /**
     * 处理请求
     */
    private static final Map<String, ISIPRequestProcessor> REQUEST_PROCESSOR_HASH_MAP = new ConcurrentHashMap<>();
    /**
     * 处理响应
     */
    private static final Map<String, ISIPResponseProcessor> RESPONSE_PROCESSOR_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();


    /**
     * 添加 request订阅
     *
     * @param method    方法名
     * @param processor 处理程序
     */
    public void addRequestProcessor(String method, ISIPRequestProcessor processor) {
        log.info("初始化请求方法[{}]处理器", method);
        REQUEST_PROCESSOR_HASH_MAP.put(method, processor);
    }

    /**
     * 添加 response订阅
     *
     * @param method    方法名
     * @param processor 处理程序
     */
    public void addResponseProcessor(String method, ISIPResponseProcessor processor) {
        log.info("初始化响应方法[{}]处理器", method);
        RESPONSE_PROCESSOR_CONCURRENT_HASH_MAP.put(method, processor);
    }

    /**
     * 添加 超时事件订阅
     *
     * @param processor 处理程序
     */
    public void addTimeoutProcessor(ITimeoutProcessor processor) {
    }

    /**
     * 处理SIP请求事件
     *
     * @param requestEvent RequestEvent事件
     */
    @Override
    public void processRequest(RequestEvent requestEvent) {
        String method = requestEvent.getRequest().getMethod();
        log.info("处理SIP请求: [{}]", method);

        ISIPRequestProcessor sipRequestProcessor = REQUEST_PROCESSOR_HASH_MAP.get(method);
        if (sipRequestProcessor == null) {
            log.warn("不支持request 方法:{}", method);
            return;
        }
        //执行具体的 ISIPRequestProcessor 实现
        REQUEST_PROCESSOR_HASH_MAP.get(method).process(requestEvent);

    }

    /**
     * 分发ResponseEvent事件
     *
     * @param responseEvent responseEvent事件
     */
    @Override
    public void processResponse(ResponseEvent responseEvent) {
        Response response = responseEvent.getResponse();
        int status = response.getStatusCode();

        log.info("处理SIP 响应: {} -> status:{}", response, status);

        // Success
        if (((status >= Response.OK) && (status < Response.MULTIPLE_CHOICES)) || status == Response.UNAUTHORIZED) {
            CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME);
            String method = cseqHeader.getMethod();
            log.info("处理SIP 响应: {} -> 响应方法：{}", response, method);
            ISIPResponseProcessor sipRequestProcessor = RESPONSE_PROCESSOR_CONCURRENT_HASH_MAP.get(method);

            if (sipRequestProcessor != null) {
                //执行具体响应 ISIPResponseProcessor
                sipRequestProcessor.process(responseEvent);
            }
        } else if ((status >= Response.TRYING) && (status < Response.OK)) {
            // 增加其它无需回复的响应，如101、180等
            log.warn("无需响应请求:{}", response);
        } else {
            log.error("接收到失败的response响应！status： {} ,message:{}", status,response.getReasonPhrase());

        }


    }

    /**
     * 向超时订阅发送消息
     *
     * @param timeoutEvent timeoutEvent事件
     */
    @Override
    public void processTimeout(TimeoutEvent timeoutEvent) {
        log.info("[消息发送超时]");
        ClientTransaction clientTransaction = timeoutEvent.getClientTransaction();

        if (clientTransaction != null) {
            log.info("[发送错误订阅] clientTransaction != null");
            Request request = clientTransaction.getRequest();
            if (request != null) {
                log.info("[发送错误订阅] request != null");
                CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME);
                if (callIdHeader != null) {

                }
            }
        }
    }

    @Override
    public void processIOException(IOExceptionEvent exceptionEvent) {
        System.out.println("processIOException");
    }

    @Override
    public void processTransactionTerminated(TransactionTerminatedEvent transactionTerminatedEvent) {

    }

    @Override
    public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) {
        CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId();
    }


}
